package drds.server.route.parser.core;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;

import drds.server.sqlparser.sqlobject.SqlObject;
import drds.server.sqlparser.sqlobject.expression.AggregateFunction;
import drds.server.sqlparser.sqlobject.expression.AllColumn;
import drds.server.sqlparser.sqlobject.expression.BetweenWithPartitionKey;
import drds.server.sqlparser.sqlobject.expression.Expression;
import drds.server.sqlparser.sqlobject.expression.InList;
import drds.server.sqlparser.sqlobject.expression.binary.BinaryExpression;
import drds.server.sqlparser.sqlobject.expression.binary.BinaryOperator;
import drds.server.sqlparser.sqlobject.expression.data_type.Text;
import drds.server.sqlparser.sqlobject.expression.name.IName;
import drds.server.sqlparser.sqlobject.expression.name.Identifier;
import drds.server.sqlparser.sqlobject.expression.name.TableAliasName$ColumnName;
import drds.server.sqlparser.sqlobject.statement.delete.DeleteStatement;
import drds.server.sqlparser.sqlobject.statement.insert.InsertStatement;
import drds.server.sqlparser.sqlobject.statement.query.GroupBy;
import drds.server.sqlparser.sqlobject.statement.query.Query;
import drds.server.sqlparser.sqlobject.statement.query.SelectItem;
import drds.server.sqlparser.sqlobject.statement.query.SelectStatement;
import drds.server.sqlparser.sqlobject.statement.query.SubQuery;
import drds.server.sqlparser.sqlobject.statement.query.order_by.OrderBy;
import drds.server.sqlparser.sqlobject.statement.query.order_by.OrderByItem;
import drds.server.sqlparser.sqlobject.statement.query.order_by.OrderByType;
import drds.server.sqlparser.sqlobject.statement.table.ExpressionTable;
import drds.server.sqlparser.sqlobject.statement.table.JoinTable;
import drds.server.sqlparser.sqlobject.statement.update.UpdateStatement;
import drds.server.sqlparser.table.Column;
import drds.server.sqlparser.table.Mode;
import drds.server.sqlparser.table.ShardKeyValue;
import drds.server.sqlparser.visitor.VisitorAdapter;
import drds.server.sqlparser.visitor.VisitorUtils;

/**
 * 解析器中用来从ast语法中提取表名、条件、字段等的vistor。切分键不做模糊查询。 我们只提取切分条件不对SQL进行优化。
 */
public class ShardInfoVisitor extends VisitorAdapter {

	/** crud */
	private Mode mode;
	/** 单表情况才允许设置该值<排除join和union表> */
	protected String currentOnlyTableName;
	/** 表和字段别名映射 */
	/** table alias */
	protected Map<String, String> tableAliasMap = new HashMap<String, String>();
	/** in select item list */
	protected Map<String, String> columnAliasMap = new HashMap<String, String>();

	//
	public void setTableAliasMap() {
		this.setTableAliasMap(new HashMap<String, String>());
	}

	public void setTableAliasMap(Map<String, String> tableAliasMap) {
		this.tableAliasMap = tableAliasMap;
	}

	public Map<String, String> getTableAliasMap() {
		if (tableAliasMap == null) {
			setTableAliasMap();
		}
		return tableAliasMap;
	}

	public void clearTableAliasMap() {
		this.tableAliasMap = null;
	}

	//
	public void setColumnAliasMap() {
		this.setColumnAliasMap(new HashMap<String, String>());
	}

	public void setColumnAliasMap(Map<String, String> columnAliasMap) {
		this.columnAliasMap = columnAliasMap;
	}

	public Map<String, String> getColumnAliasMap() {
		if (columnAliasMap == null) {
			setColumnAliasMap();
		}
		return columnAliasMap;
	}

	public void clearColumnAliasMap() {
		this.columnAliasMap = null;
	}

	/**
	 * 获取列别名对应的真实名
	 */
	protected String getColumnNameFromColumnAliasMap(String name) {
		Map<String, String> columnAliasMap = getColumnAliasMap();
		return columnAliasMap.get(name);
	}

	/**
	 * 获取表别名对应的真实名
	 */
	protected String getTableNameFromTableAliasMap(String name) {
		Map<String, String> tableAliasMap = getTableAliasMap();
		return tableAliasMap.get(name);
	}

	/** 表和字段别名映射 */
	protected Map<String, HashMap<String, Column>> tableNameToColumnNameToColumnMap = new HashMap<String, HashMap<String, Column>>();

	protected final List<Column> orderByColumnList = new ArrayList<Column>();

	public List<Column> getOrderByColumnList() {
		return orderByColumnList;
	}

	/**
	 * 根据表达式获取对应的Column(not cache)
	 * 
	 * <pre>
	 * 表达式的类型有
	 * TableName$ColumnName
	 * Identifier
	 * </pre>
	 */
	protected Column getColumn(Expression expression) {
		Map<String, String> tableAliasToTableAliasNameMap = getTableAliasMap();
		// 多表情况
		if (expression instanceof TableAliasName$ColumnName) {
			Expression tableAliasName = ((TableAliasName$ColumnName) expression).getTableAliasName();
			String columnName = ((TableAliasName$ColumnName) expression).getName();
			//
			String tableName = tableAliasToTableAliasNameMap.get(tableAliasName);
			if (tableName == null) {
				throw new NullPointerException("tableName in tableAliasToTableAliasNameMap with tableAliasName=" + tableAliasName);
			}

			Column column = addColumn(tableName, columnName);
			return column;
		} else
		// 单表情况
		if (expression instanceof Identifier) {
			// 绑定表达式
			String tableName = getCurrentOnlyTableName();
			String columnName = ((Identifier) expression).getName();
			Column column = addColumn(tableName, columnName);
			return column;
		}
		// 暂时不支持
		else {
			throw new IllegalArgumentException("else");
		}
	}

	/**
	 * 
	 * @param tableName
	 *            真实数据库表名
	 */
	public Column addColumn(String tableName, String columnName) {
		if (tableName == null) {
			throw new NullPointerException("tableName");
		}
		if (columnName == null) {
			throw new NullPointerException("columnName");
		}
		Column column = this.getColumn(tableName, columnName);
		if (column == null) {
			column = new Column(tableName, columnName);
			HashMap<String, Column> columnNameToColumnMap = tableNameToColumnNameToColumnMap.get(tableName);
			columnNameToColumnMap.put(columnName, column);
		}
		return column;
	}

	public Column getColumn(String tableName, String columnName) {
		HashMap<String, Column> columnNameToColumnMap = tableNameToColumnNameToColumnMap.get(tableName);
		if (columnNameToColumnMap == null) {
			return null;
		}
		return columnNameToColumnMap.get(columnName);
	}

	//
	public void setCurrentOnlyTableName(String tableName) {
		this.currentOnlyTableName = tableName;
	}

	public String getCurrentOnlyTableName() {
		return currentOnlyTableName;
	}

	protected Mode getMode() {
		return mode;
	}

	protected void setMode(Mode mode) {
		this.mode = mode;
	}

	public boolean visit(OrderBy x) {
		OrderByVisitor orderByVisitor = new OrderByVisitor(x);
		Query query = null;
		// () union () order by
		if (x.getParent() instanceof Query) {
			query = (Query) x.getParent();
		}
		if (query != null) {
			for (OrderByItem orderByItem : x.getOrderByItemList()) {
				Expression expression = orderByItem.getExpression();
				// 在select item中查找是否含有该项,如果不含有则添加
				for (SelectItem selectItem : query.getSelectItemList()) {
					if (selectItem.getExpression() != orderByItem.getExpression()) {
						expression.accept(orderByVisitor);
					}

				}
			}
		}
		x.accept(orderByVisitor);
		return true;
	}

	public class OrderByVisitor extends VisitorAdapter {

		private final OrderBy orderBy;

		public OrderByVisitor(OrderBy orderBy) {
			this.orderBy = orderBy;
			for (OrderByItem orderByItem : orderBy.getOrderByItemList()) {
				orderByItem.getExpression().setParent(orderByItem);
			}
		}

		public OrderBy getOrderBy() {
			return orderBy;
		}

		public boolean visit(Identifier x) {

			String columnName = x.getName();
			if (currentOnlyTableName == null) {
				throw new NullPointerException("currentOnlyTableName");
			} else {
				addOrderByColumn(currentOnlyTableName, columnName, x);
			}
			return false;
		}

		public boolean visit(TableAliasName$ColumnName x) {
			if (!(x.getTableAliasName() instanceof Identifier)) {
				throw new IllegalArgumentException("currentOnlyTableName");
			} else {
				String tableAliasName = ((Identifier) x.getTableAliasName()).getName();
				String tableName = getColumnNameFromColumnAliasMap(tableAliasName);
				addOrderByColumn(tableName, x.getName(), x);
			}
			return false;
		}

		public void addOrderByColumn(String tableName, String columnName, SqlObject sqlObject) {
			Column column = new Column(tableName, columnName);

			SqlObject parent = sqlObject.getParent();
			if (parent instanceof OrderByItem) {
				OrderByType orderByType = ((OrderByItem) parent).getOrderByType();
				column.getAttributes().put("orderBy.type", orderByType);
			}
			orderByColumnList.add(column);
		}
	}//

	public final static String _TABLE_ = "_table_";
	public final static String _COLUMN_ = "_column_";

	public boolean visit(TableAliasName$ColumnName x) {
		if (x.getTableAliasName() instanceof Identifier) {
			String tableNameOrTableAliasName = ((Identifier) x.getTableAliasName()).getName();

			String tableName = getColumnNameFromColumnAliasMap(tableNameOrTableAliasName);

			if (tableName != null) {
				Column column = addColumn(tableName, x.getName());
				x.putAttribute(_COLUMN_, column);
				if (column != null) {
					/** 设置处于的位置 */
					/** @see Column */
					setColumnPostion(x, column);
				}
			}
		}
		return false;
	}

	private void setColumnPostion(Expression x, Column column) {
		SqlObject current = x;
		for (;;) {
			SqlObject parent = current.getParent();

			if (parent == null) {
				break;
			}

			if (isParentSelectItem(parent)) {
				column.setSelectItem(true);
				break;
			}
			if (parent instanceof Query) {
				Query query = (Query) parent;
				if (query.getWhere() == current) {
					column.setWhere(true);
				}
				break;
			}
			if (parent instanceof JoinTable) {
				JoinTable joinTable = (JoinTable) parent;
				if (joinTable.getOn() == current) {
					column.setJoin(true);
				}
				break;
			}

			if (parent instanceof GroupBy) {
				GroupBy groupBy = (GroupBy) parent;
				if (groupBy.getGroupByItemList().contains(current)) {
					column.setGroupBy(true);
				} else if (current == groupBy.getFilter()) {
					column.setGroupByFilter(true);
				}
				break;
			}
			current = parent;
		}
	}

	/**
	 * 最外层是否是select item
	 */
	private boolean isParentSelectItem(SqlObject parent) {
		if (parent == null) {
			return false;
		}
		if (parent instanceof SelectItem) {
			return true;
		}
		return isParentSelectItem(parent.getParent());
	}

	//

	protected void accept(SqlObject x) {
		if (x != null) {
			x.accept(this);
		}
	}

	protected void accept(List<? extends SqlObject> list) {
		for (int i = 0, size = list.size(); i < size; ++i) {
			accept(list.get(i));
		}
	}

	public boolean visit(SelectStatement x) {
		setTableAliasMap();
		setColumnAliasMap();
		return true;
	}

	public boolean visit(Query x) {
		setMode(Mode.Select);
		if (x.getFrom() instanceof ExpressionTable) {
			ExpressionTable expressionTable = (ExpressionTable) x.getFrom();
			if (expressionTable.getExpression() instanceof IName) {
				String tableName = expressionTable.getExpression().toString();
				x.putAttribute(_TABLE_, tableName);
			}
		}

		if (x.getWhere() != null) {
			x.getWhere().setParent(x);
		}

		return true;
	}

	public boolean visit(SubQuery x) {
		accept(x.getIQuery());
		String originalTable = getCurrentOnlyTableName();

		setCurrentOnlyTableName((String) x.getIQuery().toString());

		setCurrentOnlyTableName(originalTable);

		return false;
	}

	public boolean visit(SelectItem x) {
		x.getExpression().accept(this);
		String alias = x.getAlias();

		Map<String, String> columnAliasMap = this.getColumnAliasMap();

		if (alias != null) {
			if (x.getExpression() instanceof TableAliasName$ColumnName) {
				columnAliasMap.put(alias, x.getExpression().toString());
			} else if (x.getExpression() instanceof IName) {
				columnAliasMap.put(alias, x.getExpression().toString());
			} else {
				throw new IllegalArgumentException("else");
			}
		}

		return false;
	}

	//
	public boolean visit(AggregateFunction x) {
		accept(x.getArgumentList());
		return false;
	}

	public boolean visit(AllColumn x) {
		if (x.getParent() instanceof AggregateFunction) {
			AggregateFunction aggregateFunction = (AggregateFunction) x.getParent();
			if ("count".equalsIgnoreCase(aggregateFunction.getMethodName())) {
				return false;
			}
		}
		return false;
	}

	public boolean visit(ExpressionTable x) {
		if (!(x.getExpression() instanceof IName)) {
			throw new IllegalArgumentException("只支持直接表名");
		} else {
			String tableName = x.getExpression().toString();
			String alias = x.getAlias();
			Map<String, String> tableAliasMap = getTableAliasMap();
			tableAliasMap.put(alias, tableName);

		}

		return false;
	}

	public boolean visit(JoinTable x) {
		x.getLeft().accept(this);
		x.getRight().accept(this);
		if (x.getOn() != null) {
			// 从切分条件获得具体在那个库上面进行join范围的查找
			x.getOn().accept(this);
		}
		return false;
	}

	//
	@Override
	public boolean visit(InsertStatement x) {
		setMode(Mode.Insert);

		String tableName = ((IName) x.getTableName()).toString();
		setCurrentOnlyTableName(tableName);
		accept(x.getColumnNameList());

		return false;
	}

	public boolean visit(UpdateStatement x) {
		setTableAliasMap();
		setMode(Mode.Update);
		String tableName = x.getTableName().toString();
		setCurrentOnlyTableName(tableName);
		accept(x.getUpdateItemList());
		accept(x.getWhere());

		return false;
	}

	public boolean visit(DeleteStatement x) {
		setTableAliasMap();
		setMode(Mode.Delete);
		String tableName = x.getTableName().toString();
		setCurrentOnlyTableName(tableName);
		accept(x.getWhere());

		return false;
	}

	public boolean visit(InList x) {
		if (x.isNot()) {
			addShardKeyValue(x.getExpression(), "not in", x.getItemList());
		} else {
			addShardKeyValue(x.getExpression(), "in", x.getItemList());
		}
		return true;
	}

	/**********************************************************************************/
	/** 切分条件 */
	protected final List<ShardKeyValue> shardKeyValueList = new ArrayList<ShardKeyValue>();

	protected void addShardKeyValue(//
			Expression expression,//
			String operator,//
			List<Expression> valueList) {//
		addShardKeyValue(expression, operator, valueList.toArray(new Expression[valueList.size()]));
	}

	protected void addShardKeyValue(//
			Expression expression,//
			String operator, //
			Expression... valueList) {//

		Column column = getColumn(expression);
		ShardKeyValue shardKeyValue = new ShardKeyValue();
		shardKeyValue.setColumn(column);
		shardKeyValue.setOperator(operator);

		for (Expression valueExpression : valueList) {
			/**
			 * 切分条件是具体的值
			 */
			shardKeyValue.getValueList().add(valueExpression);
		}
		this.shardKeyValueList.add(shardKeyValue);
	}

	// 判断BinaryExpression是否还有or操作符号
	private boolean hasOr = false;
	private List<SplitableExpression> splitableExpressionList = new CopyOnWriteArrayList<SplitableExpression>();

	public boolean hasOr() {
		return hasOr;
	}

	public List<ShardKeyValue> getShardKeyValueList() {
		return shardKeyValueList;
	}

	public List<SplitableExpression> getConditionsList() {
		return splitableExpressionList;
	}

	private void reset() {
		this.shardKeyValueList.clear();
		this.splitableExpressionList.clear();
		this.hasOr = false;
	}

	@Override
	public boolean visit(BinaryExpression x) {
		x.getLeft().setParent(x);
		x.getRight().setParent(x);
		//
		switch (x.getBinaryOperator()) {

		case Or:
			// 二元表达式
			hasOr = true;
			SplitableExpression splitableExpression = null;
			if (shardKeyValueList.size() > 0) {
				splitableExpression = new SplitableExpression();
				splitableExpression.setFinishedParse(true);
				splitableExpression.addOutSideShardKeyValueList(getShardKeyValueList());
				//
				SplitableExpression innerSplitableExpression = new SplitableExpression(x);
				splitableExpression.addInnerSplitableExpression(innerSplitableExpression);
			} else {
				splitableExpression = new SplitableExpression(x);
				splitableExpression.addOutSideShardKeyValueList(getShardKeyValueList());
			}
			splitableExpressionList.add(splitableExpression);

			return false;
			/***************************************************************/
			/** 对切分条件进行替换 */
			/***************************************************************/
		case PartitionKeyEq:
			//
		case PartitionKeyLessThan:
		case PartitionKeyLessThanOrEqual:
			//
		case PartitionKeyGreaterThan:
		case PartitionKeyGreaterThanOrEqual:
			addShardKeyValue(x.getLeft(), x.getBinaryOperator().name, x.getRight());
			break;
		case Is:
		case IsNot:
			//
			//
		case Like:
		case NotLike:
			//
		case Equal:
		case NotEqual:
			//
		case LessThan:
		case LessThanOrEqual:
			//
		case GreaterThan:
		case GreaterThanOrEqual:
		default:
			break;
		}
		return true;
	}

	/**
	 * <pre>
	 * // int 时间戳格式，查询 2008-08-08 20:00:00 到 2009-01-01 零点之前的数据
	 * SELECT * FROM table WHERE column_time BETWEEN 1218196800 AND 1230739199
	 * 
	 * // DATE 格式，查询 2008-08-08 到 2009-01-01 零点之前的数据
	 * SELECT * FROM table WHERE column_time BETWEEN '2008-08-08' AND '2009-01-01'
	 * 
	 * // DATETIME 格式，查询 2008-08-08 20:00:00 到 2009-01-01 零点之前的数据
	 * SELECT * FROM table WHERE column_time BETWEEN '2008-08-08 20:00:00' AND '2008-12-31 23:59:59'
	 * </pre>
	 */
	@Override
	public boolean visit(BetweenWithPartitionKey x) {
		String begin = null;
		String end = null;
		/**
		 * 支持日期和数字
		 */
		if (x.begin instanceof Text) {
			begin = (String) ((Text) x.begin).getText();
		} else {
			begin = x.begin.toString();
		}

		if (x.end instanceof Text) {
			end = (String) ((Text) x.end).getText();
		} else {
			end = x.end.toString();
		}
		//
		Column column = getColumn(x.get$());
		ShardKeyValue shardKeyValue = null;
		for (ShardKeyValue _ : this.getShardKeyValueList()) {
			if (_.getColumn().equals(column) && _.getOperator().equals("between")) {
				shardKeyValue = _;
				throw new IllegalArgumentException("一个条件只能有一个");
			}
		}

		if (shardKeyValue == null) {
			shardKeyValue = new ShardKeyValue();
			shardKeyValue.setColumn(column);
			shardKeyValue.setOperator("between");
			this.shardKeyValueList.add(shardKeyValue);
		}

		shardKeyValue.getValueList().add(begin);
		shardKeyValue.getValueList().add(end);

		return true;
	}

	/**
	 * 判断条件是否永真
	 */
	public static boolean isConditionAlwaysTrue(Expression expression) {
		Object o = VisitorUtils.getValue(expression);
		if (Boolean.TRUE.equals(o)) {
			return true;
		}
		return false;
	}

	/**
	 * 判断条件是否永假的
	 */
	public static boolean isConditionAlwaysFalse(Expression expr) {
		Object o = VisitorUtils.getValue(expr);
		if (Boolean.FALSE.equals(o)) {
			return true;
		}
		return false;
	}

	/**
	 * 分解条件
	 */
	public List<List<ShardKeyValue>> split() {
		// 按照or拆分
		for (SplitableExpression splitableExpression : splitableExpressionList) {
			splitIfExistsOr(splitableExpression);
		}
		List<SplitableExpression> tempSplitableExpressionList = new CopyOnWriteArrayList<SplitableExpression>();

		tempSplitableExpressionList.addAll(splitableExpressionList);

		loopByOr(splitableExpressionList);

		for (SplitableExpression splitableExpression : tempSplitableExpressionList) {
			/**
			 * 解析为ConditionListList
			 */
			extractConditionListFrom(splitableExpression);
		}

		/**
		 * ConditionListList M*N组和
		 */
		return mergeConditionListList(tempSplitableExpressionList);
	}

	/**
	 * 循环寻找子Conditions（实际是嵌套的or）
	 * 
	 */
	private void loopByOr(List<SplitableExpression> conditionsList) {
		List<SplitableExpression> subConditionsList = new ArrayList<SplitableExpression>();
		for (SplitableExpression conditions : conditionsList) {
			if (conditions.getBinaryExpressionList().size() > 0) {
				List<Expression> removeSplitedList = new ArrayList<Expression>();
				for (Expression expression : conditions.getBinaryExpressionList()) {
					reset();
					if (isHasOr(expression)) {
						removeSplitedList.add(expression);
						SplitableExpression subConditions = this.splitableExpressionList.get(0);
						splitIfExistsOr(subConditions);
						conditions.addInnerSplitableExpression(subConditions);
						subConditionsList.add(subConditions);
					} else {
						this.shardKeyValueList.clear();
					}
				}// end
				if (removeSplitedList.size() > 0) {
					conditions.getBinaryExpressionList().removeAll(removeSplitedList);
				}
			}
			subConditionsList.addAll(conditions.getInnerSplitableExpressionList());
		}//

		if (subConditionsList.size() > 0) {
			loopByOr(subConditionsList);
		}
	}

	private boolean isHasOr(Expression expression) {
		expression.accept(this);
		return hasOr;
	}

	private List<List<ShardKeyValue>> mergeConditionListList(List<SplitableExpression> conditionsList) {
		if (conditionsList.size() == 0) {
			return new ArrayList<List<ShardKeyValue>>();
		}
		for (SplitableExpression conditions : conditionsList) {
			mergeInnerConditionsList(conditions);
		}
		return mergeInnerConditionsList(conditionsList);

	}

	private void mergeInnerConditionsList(SplitableExpression conditions) {
		if (conditions.getInnerSplitableExpressionList().size() > 0) {
			for (SplitableExpression innerConditions : conditions.getInnerSplitableExpressionList()) {
				mergeInnerConditionsList(innerConditions);
			}

			if (conditions.getInnerSplitableExpressionList().size() > 1) {
				List<List<ShardKeyValue>> conditionListList = mergeInnerConditionsList(conditions.getInnerSplitableExpressionList());
				if (conditions.getOutSideShardKeyValueList().size() > 0) {
					List<ShardKeyValue> outSideConditionsList = conditions.getOutSideShardKeyValueList();
					int size = conditionListList.size();
					for (int i = 0; i < size; i++) {
						// 得到引用
						conditionListList.get(i).// list
								addAll(outSideConditionsList);
					}
				}
				conditions.setShardKeyValueListList(conditionListList);
			} else if (conditions.getInnerSplitableExpressionList().size() == 1) {
				if (conditions.getOutSideShardKeyValueList().size() > 0 && //
						conditions.getInnerSplitableExpressionList().get(0).//
								getShardKeyValueListList().size() > 0) {
					int size = conditions.getInnerSplitableExpressionList().get(0).//
							getShardKeyValueListList().size();
					for (int i = 0; i < size; i++) {// list
						conditions.getInnerSplitableExpressionList().get(0).//
								getShardKeyValueListList().get(i). //
								addAll(conditions.getOutSideShardKeyValueList());
					}
				}
				conditions.getShardKeyValueListList().addAll(//
						conditions.getInnerSplitableExpressionList().get(0).//
								getShardKeyValueListList());//
			}
		} else {
			// do nothing
		}
	}

	/**
	 * 条件全排列((m*n)*o)*p...
	 */
	private List<List<ShardKeyValue>> mergeInnerConditionsList(List<SplitableExpression> conditionsList) {
		List<List<ShardKeyValue>> conditionListList = new ArrayList<List<ShardKeyValue>>();
		if (conditionsList.size() == 0) {
			return conditionListList;
		}
		conditionListList.addAll(//
				conditionsList.get(0).getShardKeyValueListList()//
				);//

		for (int i = 1; i < conditionsList.size(); i++) {
			conditionListList = mn(//
					conditionListList, //
					conditionsList.get(i).getShardKeyValueListList()//
			);//
		}
		return conditionListList;
	}

	/**
	 * 两个list中的条件m*n组合
	 */
	private List<List<ShardKeyValue>> mn(//
			List<List<ShardKeyValue>> left,//
			List<List<ShardKeyValue>> right//
	) {
		if (left.size() == 0) {
			return right;
		} else if (right.size() == 0) {
			return left;
		}

		List<List<ShardKeyValue>> listList = new ArrayList<List<ShardKeyValue>>();
		/**
		 * m*n次组和
		 */
		for (int m = 0; m < left.size(); m++) {
			for (int n = 0; n < right.size(); n++) {
				List<ShardKeyValue> list = new ArrayList<ShardKeyValue>();
				list.addAll(left.get(m));
				list.addAll(right.get(n));
				listList.add(list);
			}
		}
		return listList;
	}

	private void extractConditionListFrom(SplitableExpression splitableExpression) {
		List<List<ShardKeyValue>> shardKeyValueListList = new ArrayList<List<ShardKeyValue>>();
		// or语句外层的条件:如where condition1 and (condition2 or
		// condition3),condition1就会在外层条件中,因为之前提取
		List<ShardKeyValue> outSideShardKeyValueList = new ArrayList<ShardKeyValue>();
		// stashOutSideConditions();
		outSideShardKeyValueList.addAll(shardKeyValueList);
		this.shardKeyValueList.clear();
		//
		for (Expression expression : splitableExpression.getBinaryExpressionList()) {
			/**
			 * 遍历获取条件
			 */
			expression.accept(this);// 解析出conditionList

			List<ShardKeyValue> conditionList = new ArrayList<ShardKeyValue>();
			conditionList.addAll(outSideShardKeyValueList);
			conditionList.addAll(this.shardKeyValueList);
			this.shardKeyValueList.clear();
			//
			shardKeyValueListList.add(conditionList);

		}
		splitableExpression.setShardKeyValueListList(shardKeyValueListList);
		//
		for (SplitableExpression innerSplitableExpression : splitableExpression.getInnerSplitableExpressionList()) {
			extractConditionListFrom(innerSplitableExpression);
		}
	}

	/**
	 * 递归拆分OR
	 * 
	 * <pre>
	 * 
	 * 现在最多只支持弱复杂度SQL,对于子查询和exists暂时不支持.
	 * </pre>
	 * 
	 * @param splitableExpression
	 *            TODO:考虑嵌套or语句，条件中有子查询、 exists等很多种复杂情况是否能兼容
	 */
	private void splitIfExistsOr(SplitableExpression splitableExpression) {
		if (splitableExpression.isFinishedParse()) {
			// 如果对where解析成功则需要对子whereList进行解析
			if (splitableExpression.getInnerSplitableExpressionList().size() > 0) {
				int size = splitableExpression.getInnerSplitableExpressionList().size();
				for (int i = 0; i < size; i++) {
					// 内层条件解析
					splitIfExistsOr(splitableExpression.getInnerSplitableExpressionList().get(i));
				}
			}
		} else {
			//
			BinaryExpression binaryExpression = splitableExpression.getBinaryExpression();
			if (binaryExpression.getBinaryOperator() != BinaryOperator.Or) {
				addExpressionIfNotFalse(splitableExpression, binaryExpression);
				splitableExpression.setFinishedParse(true);
			} else {
				// bug
				addExpressionIfNotFalse(splitableExpression, binaryExpression.getRight());
				// (a or b ) or c (a or b ( c or d)) or e
				// 由上面推出一个同一个层级的就是一组Conditions
				if (!(binaryExpression.getLeft() instanceof BinaryExpression)) {
					addExpressionIfNotFalse(splitableExpression, binaryExpression.getLeft());
				} else {
					splitableExpression.setBinaryExpression((BinaryExpression) binaryExpression.getLeft());
					splitIfExistsOr(splitableExpression);
				}

			}
		}
	}

	private void addExpressionIfNotFalse(//
			SplitableExpression splitableExpression, //
			Expression expression) {//
		// 非永假条件加入路由计算
		if (!isConditionAlwaysFalse(expression)) {
			splitableExpression.addBinaryExpression(expression);
		}
	}

}
